package com.ruiysoft.service.order.impl;

import com.alibaba.fastjson.JSON;
import com.ruiysoft.controller.cart.InnrCartApi;
import com.ruiysoft.controller.mdse.InnrApi;
import com.ruiysoft.controller.mdse.vo.OrderSkuListVo;
import com.ruiysoft.controller.order.vo.*;
import com.ruiysoft.entity.common.UserInfo;
import com.ruiysoft.entity.order.*;
import com.ruiysoft.entity.sys.SysMicroShop;
import com.ruiysoft.pub.anno.DuplicateLock;
import com.ruiysoft.pub.core.Result;
import com.ruiysoft.pub.core.ResultCode;
import com.ruiysoft.pub.core.ResultGenerator;
import com.ruiysoft.pub.entity.PageInfo;
import com.ruiysoft.service.integral.IIntegralService;
import com.ruiysoft.service.mdse.bean.MerchandiseStoceEnvelope;
import com.ruiysoft.service.order.IOrderMonitor;
import com.ruiysoft.service.order.IOrderWechatService;
import com.ruiysoft.service.order.anno.OrderOperate;
import com.ruiysoft.service.order.bean.OrderDto;
import com.ruiysoft.service.order.bean.OrderIntfResultDto;
import com.ruiysoft.service.order.bean.OrderPlaceSkuInfoVo;
import com.ruiysoft.service.order.bean.OrderSkuDto;
import com.ruiysoft.service.order.consts.OrderBizTypeEnum;
import com.ruiysoft.service.order.consts.OrderDBStatusEnum;
import com.ruiysoft.service.order.consts.OrderOperateTypeEnum;
import com.ruiysoft.service.order.consts.OrderTypeEnum;
import com.ruiysoft.service.order.facade.*;
import com.ruiysoft.service.order.util.OrderCheckUtil;
import com.ruiysoft.service.order.util.OrderWechatUtil;
import com.ruiysoft.service.sys.ISysMicroShopService;
import com.ruiysoft.sms.service.SmsService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Date : 2018/11/2
 *
 * @author WenJialu
 */
@Service
public class OrderWechatServiceImpl implements IOrderWechatService {

    private static final Logger logger = LoggerFactory.getLogger(OrderWechatServiceImpl.class);

    @Resource
    private OrderPubFacade oPubFacade;
    @Resource
    private OrderWechatFacade oWechatFacade;
    @Resource
    private OrderAssembleFacade oAssembleFacade;
    @Resource
    private OrderCalculateFacade oCalculateFacade;
    @Resource
    private OrderDBHandleFacade oDBHandleFacade;
    @Resource
    private InnrApi innrMdseApi;
    @Resource
    private InnrCartApi innrCartApi;
    @Resource
    OrderCheckUtil orderCheckUtil;
    @Resource
    IOrderMonitor orderMonitor;

    @Autowired
    IIntegralService integralService;
    @Autowired
    ISysMicroShopService shopService;
//
    @Resource
    SmsService smsService;

    /**
     * 订单详情
     *
     * @param orderNo
     * @return
     */
    @Override
    public OrderDto findOrderWithDetailByOrderNo(String orderNo) {
        if (StringUtils.isBlank(orderNo)) {
            return null;
        } else {
            //订单主表信息
            OrderMain orderMain = oWechatFacade.getOrderMain(orderNo);
            return findOrderDetail(orderMain);
        }
    }

    @Override
    public OrderDto findOrderWithDetailByOrderNo(UserInfo userInfo, String orderNo) {
        OrderMain orderMain = oWechatFacade.getOrderMain(orderNo);
        if (!userInfo.getPersonnelId().equals(orderMain.getUserId()) || !userInfo.getShopId().equals(orderMain.getShopId())) {
            return null;
        }
        return findOrderDetail(orderMain);
    }

    @Override
    public OrderDto findOrderWithDetailByOrderNo(Long shopId, String orderNo) {
        //订单主表信息
        OrderMain orderMain = oWechatFacade.getOrderMain(orderNo);
        if (orderMain == null) {
            throw new RuntimeException(String.format("不存在此订单号[%s]", orderNo));
        } else if (!shopId.equals(orderMain.getShopId())) {
            throw new RuntimeException(String.format("店铺信息不匹配%d与%d", shopId.longValue(), orderMain.getId().longValue()));
        }
        return findOrderDetail(orderMain);
    }

    /**
     * 订单列表
     *
     * @param userInfo
     * @param status
     * @param pageStart
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<OrderDto> findOrders(UserInfo userInfo, @Valid Set<Integer> status, @NotNull @Valid Integer pageStart, @NotNull @Valid Integer pageSize) {
        //获取订单主表列表
        PageInfo<OrderMain> orderMainsPage = oWechatFacade.getOrdersByCustomerStatusPage(userInfo, status, pageStart, pageSize);
        if (!orderMainsPage.getList().isEmpty()) {
            List<OrderDto> orderList = orderMainsPage.getList()
                    .stream()
                    //.map(orderMain -> findOrderWithDetailByOrderNo(orderMain.getOrderNo()))
                    .map(orderMain -> findOrderDetail(orderMain))
                    .collect(Collectors.toList());
            return new PageInfo<>(orderList, pageStart, pageSize, orderMainsPage.getTotalCount());
        } else {
            return new PageInfo<>();
        }
    }

    /**
     * 前端支付后调用
     * @param userInfo
     * @param orderNo
     * @param isPaidSuccess
     * @return
     */
    @Override
    @Transactional
    public Result<Void> frontendPaid(UserInfo userInfo, String orderNo, boolean isPaidSuccess) {
        OrderMain orderMain = oWechatFacade.getOrderMain(orderNo);
        if(userInfo.getPersonnelId().compareTo(orderMain.getUserId()) != 0){
            throw new RuntimeException("非法操作订单.");
        }
        logger.info("支付成功,店铺Id="+orderMain.getShopId());
//        //支付成功之后给店家发送短信
        SysMicroShop shop = shopService.selectSysMicroShopById(orderMain.getShopId());
        logger.info("店铺手机号是="+shop.getTelephone());
        smsService.sendPlaceAnOrder(shop.getTelephone(),orderNo);
        logger.info("开始执行魏雪刚的返佣比例计算");
        shopService.calculationWxg(orderMain);
        //扣减各种系统内的东西
        if(!isPaidSuccess) {
            Long ReceivableVirtualCoin = Optional.ofNullable(orderMain.getReceivableVirtualCoin()).orElse(0L);

            if (ReceivableVirtualCoin.longValue() > 0) {
                //退回虚拟币
                integralService.refund(
                        userInfo.getShopId(),
                        userInfo.getPersonnelId(),
                        ReceivableVirtualCoin,
                        orderMain.getOrderNo());
                //更新订单表虚拟币信息
                //需要关心订单状态
            }
        }else {
            if (Optional.ofNullable(orderMain.getReceivableAmount()).orElse(0L).longValue() == 0) {
                orderMain.setStatus(OrderDBStatusEnum.PLATFORM_CONFIRMED_WAITING_FOR_SHOP_CONFIRM.getCode());
            }
            orderMain.setCollectedVirtualCoin(orderMain.getReceivableVirtualCoin());
            oWechatFacade.orderVirtualCoinPaid(orderMain, userInfo.getPersonnelId());
        }
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 订单预览 运费 商品信息等
     *
     * @param orderPlaceVo
     * @return
     */
    @Override
    public Result<OrderIntfResultDto> orderPrePlace(ShopVO shopVO, OrderBuyerVO buyerVO, @Valid OrderPlaceCusVo orderPlaceVo) {
        Result<OrderIntfResultDto> result = orderCheckUtil.checkOrderPrePlaceCustomer(orderPlaceVo);
        if (!result.isSuccess()) {
            return result;
        } else {
            //组装业务数据
            //获取sku信息
            List<OrderPlaceSkuCusVo> orderPlaceSkus = orderPlaceVo.getOrderPlaceSkus();
            if (logger.isTraceEnabled()) {
                logger.trace("OrderPrePlace/input sku info:{}", JSON.toJSONString(orderPlaceSkus));
            }
            List<Long> inputSKUs = new ArrayList<>();
            for (OrderPlaceSkuCusVo orderPlaceSkuCusVo : orderPlaceSkus) {
                Long skuId = orderPlaceSkuCusVo.getSkuId();
                inputSKUs.add(skuId);
            }
            //查询信息
            Result<Map<Long, OrderSkuListVo>> skuInfoResult = innrMdseApi.innrMdseSkuListOrderPost(inputSKUs, buyerVO.getMemberLevel().get());
            if (logger.isTraceEnabled()) {
                logger.trace("OrderPrePlace/sku info from mdse system:{}", JSON.toJSONString(orderPlaceSkus));
            }

            if (null == skuInfoResult || !skuInfoResult.isSuccess() || null == skuInfoResult.getData() || skuInfoResult.getData().isEmpty()) {
                return ResultGenerator.genFailResult("未查询到商品信息");
            }

            Map<Long, OrderSkuListVo> skuInfoMap = skuInfoResult.getData();
            if (orderPlaceSkus.stream().map(OrderPlaceSkuCusVo::getSkuId).collect(Collectors.toSet()).size()
                    != skuInfoMap.keySet().size()) {
                return ResultGenerator.genFailResult("商品信息不匹配");
            }

            OrderIntfResultDto dto = new OrderIntfResultDto();
            dto.setOrderPlaceSkuInfoVos(OrderParseFacade.INSTANCE.parseOrderPlaceSkus(orderPlaceSkus, skuInfoMap));
            dto.setOrderReceiverInfoVo(orderPlaceVo.getOrderReceiverInfoVo());
            dto.setOrderMain(new OrderMain());
            Result calculateResult = oCalculateFacade.calculateOrderInPlace(shopVO, buyerVO, dto);
            calculateResult.setData(dto);
            return calculateResult;
        }
    }

    @Override
    public OrderReceiverInfo findLastestReceiverInfo(Long userId) {
        return oWechatFacade.getLastestReceiverInfo(userId);
    }


    /**
     * 取消订单：无需验证用户，此接口进攻后台调用
     * @param orderNo Order NO.
     * @return
     */
    @Override
    @Transactional
    public Result orderCancel(String orderNo,String remark) {
        OrderMain orderMain = oWechatFacade.getOrderMain(orderNo);
        return orderCancel(orderNo, orderMain.getUserId(),remark);
    }

    /**
     * 取消订单
     * @param orderNo Order NO.
     * @param userId User ID
     * @param remark remark
     * @return
     */
    @Override
    @Transactional
    @OrderOperate(orderNo = "#orderNo", operateType = OrderOperateTypeEnum.ORDER_CANCELL, operatorId = "#userId")
    public Result orderCancel(String orderNo, Long userId, String remark) {
        if (StringUtils.isBlank(orderNo)) {
            return ResultGenerator.genFailResult("订单号不能为空");
        }
        //操作记录

        //主表
        Result result = oWechatFacade.orderMainCancel(orderNo, userId, remark);
        if (result.isSuccess()) {
            //取消支付
            oWechatFacade.orderPayCancel(orderNo);
            //获取订单商品
            List<OrderDetail> orderDetails = oPubFacade.getOrderDetails(orderNo);
            //库存
            innrMdseApi.innrMdseDerBatchPost(orderDetails
                    .stream()
                    .map(vo -> new MerchandiseStoceEnvelope()
                            .setSkuId(vo.getSkuId())
                            .setNum(0 - vo.getQuantity()))
                    .collect(Collectors.toList()));

            //退还虚拟币
            OrderMain orderMain = oWechatFacade.getOrderMain(orderNo);
            if(userId.compareTo(orderMain.getUserId()) != 0){
                throw new RuntimeException("非法操作订单.");
            }
            Long ReceivableVirtualCoin = Optional.ofNullable(orderMain.getReceivableVirtualCoin()).orElse(0L);
            if (ReceivableVirtualCoin.longValue() > 0) {
                //退回虚拟币
                integralService.refund(
                        orderMain.getShopId(),
                        orderMain.getUserId(),
                        ReceivableVirtualCoin,
                        orderMain.getOrderNo());
                //更新订单表虚拟币信息
                //需要关心订单状态
            }

            return ResultGenerator.genSuccessResult();
        } else {
            return result;
        }
    }

    /**
     * 确认收货
     *
     * @param orderNo
     * @return
     */
    @Override
    @Transactional
    @OrderOperate(orderNo = "#orderNo", operateType = OrderOperateTypeEnum.RECEIVE_CONFIRM, operatorId = "#userId")
    public Result<OrderMain> orderConfirmReceipt(String orderNo, Long userId) {
        if (StringUtils.isEmpty(orderNo)) {
            return ResultGenerator.genFailResult("订单号不能为空");
        }
        //操作记录
        //主表
        return oWechatFacade.orderConfirmReceipt(orderNo, userId);

    }

    /**
     * 确认订单（下单）时即扣减虚拟币
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @DuplicateLock(key = "#orderPlaceVo", userId = "#userInfo.personnelId")
    @OrderOperate(orderNo = "#result.data.orderNo", operateType = OrderOperateTypeEnum.ORDER_CREATE, operatorId = "#userInfo.personnelId")
    @Order(3)
    public Result<OrderIntfResultDto> orderPlace(UserInfo userInfo, @Valid OrderIntfResultDto orderIntfResultDto) {
        Result<OrderIntfResultDto> result = new Result<>();
        result.setData(orderIntfResultDto);

        //解析组装skuBean
        List<OrderPlaceSkuInfoVo> orderPlaceSkuInfoVos = orderIntfResultDto.getOrderPlaceSkuInfoVos();
        OrderReceiverInfoVo orderReceiverInfoVo = orderIntfResultDto.getOrderReceiverInfoVo();


        //订单主表
        OrderMain orderMain = oAssembleFacade.assembleOrderMain(userInfo, OrderTypeEnum.CUSTOMER_ROUTINE_ORDER, OrderBizTypeEnum.COMMON_GOODS_ORDER, orderIntfResultDto.getOrderMain());
        orderMain.setCollectedVirtualCoin(orderMain.getReceivableVirtualCoin());
        oDBHandleFacade.insertOrderMain(orderMain);

        //扣减虚拟币
        Long ReceivableVirtualCoin = Optional.ofNullable(orderMain.getReceivableVirtualCoin()).orElse(0L);

        if (ReceivableVirtualCoin.longValue() > 0) {
            //更新订单表虚拟币信息
            integralService.consume(
                    userInfo.getShopId(),
                    userInfo.getPersonnelId(),
                    ReceivableVirtualCoin,
                    orderMain.getOrderNo());
        }

        //订单支付
        OrderPay orderPay = oAssembleFacade.assembleOrderPay(orderMain);
        oDBHandleFacade.insertOrderPay(orderPay);

        //订单明细
        List<OrderDetail> orderDetails = oAssembleFacade.assembleOrderDetails(orderMain, orderPlaceSkuInfoVos);
        oDBHandleFacade.insertOrderDetails(orderDetails);

        //sku信息
        List<OrderSkuInfo> orderSkuInfos = oAssembleFacade.assembleOrderSkuInfos(orderMain, orderPlaceSkuInfoVos);
        oDBHandleFacade.insertOrderSkuInfos(orderSkuInfos);

        //sku图片
        List<OrderSkuPic> orderSkuPics = oAssembleFacade.assembleOrderSkuPic(orderMain, orderPlaceSkuInfoVos);
        oDBHandleFacade.insertOrderSkuPics(orderSkuPics);

        //收货人信息
        OrderReceiverInfo orderReceiverInfo = oAssembleFacade.assembleOrderReceiverInfo(orderMain, orderReceiverInfoVo);
        oDBHandleFacade.insertOrderReceiverInfo(orderReceiverInfo);

        //操作记录

        //库存
        innrMdseApi.innrMdseDerBatchPost(orderPlaceSkuInfoVos
                .stream()
                .map(vo -> {
                    MerchandiseStoceEnvelope mse = new MerchandiseStoceEnvelope();
                    mse.setSkuId(vo.getSkuId());
                    mse.setNum(vo.getQuantity());
                    return mse;
                })
                .collect(Collectors.toList()));

        //购物车
        innrCartApi.innrCartCartDelPost(userInfo.getShopId(), userInfo.getPersonnelId(), orderPlaceSkuInfoVos
                .stream()
                .map(OrderPlaceSkuInfoVo::getSkuId)
                .collect(Collectors.toList()));

        //支付延时取消
        orderMonitor.commitMonitor(orderMain.getOrderNo());

        OrderIntfResultDto dto = new OrderIntfResultDto();
        dto.setOrderMain(orderMain);
        dto.setOrderNo(orderMain.getOrderNo());
        dto.setFreight(orderMain.getFreight());
        dto.setMdseReceivableAmount(orderMain.getMdseReceivableAmount());
        dto.setReceivableAmount(orderMain.getReceivableAmount());
        result.setData(dto);
        result.setBizCode(ResultCode.CODE_SUCCESS);
        return result;

    }



    public OrderDto findOrderDetail(OrderMain orderMain) {
        if (orderMain == null || StringUtils.isBlank(orderMain.getOrderNo())) {
            return null;
        }
        String orderNo = orderMain.getOrderNo();
        OrderDto dto = new OrderDto();
        dto.setOrderMain(orderMain);
        //订单sku信息
        //订单详情
        List<OrderDetail> orderDetails = oPubFacade.getOrderDetails(orderNo);
        //订单sku
        List<OrderSkuInfo> orderSkuInfos = oPubFacade.getOrderSkuInfos(orderNo);
        //订单sku首张图片
        Map<Long, String> orderSkuPicsMap = oPubFacade.getOrderSkuFirstPics(orderNo);
        List<OrderSkuDto> skuDtos = OrderWechatUtil.INSTANCE.assembleOrderSkuDtos(orderDetails, orderSkuInfos, orderSkuPicsMap);
        dto.setOrderSkuDtos(skuDtos);
        //订单收货人信息
        OrderReceiverInfo receiverInfo = oPubFacade.getOrderReceiverInfo(orderNo);
        dto.setOrderReceiverInfo(receiverInfo);
        //订单物流号
        List<OrderLogistics> orderLogisticsList = oPubFacade.getOrderLogisticsList(orderNo);
        if (orderLogisticsList != null && orderLogisticsList.size() > 0) {
            dto.setOrderLogisticsList(orderLogisticsList);
        }
        return dto;

    }

}
